package org.matchit.selection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.hamcrest.Matcher;

/**
 * Allows elements to be selected from a collection, using {@link Matcher} logic.
 * 
 * <pre>
 *  peopleWithLongNames = from(persons).where(hasLongName);
 * </pre>
 * 
 * @author Jeroen van Schagen
 * @since 18-03-2011
 *
 * @param <T> the type of content being filtered on
 */
public class Selector<T> {
    private final List<T> content;

    /**
     * Construct a new {@link Selector}.
     * @param content the elements we can search on
     */
    private Selector(Collection<T> content) {
        this.content = new LinkedList<T>(content);
    }

    /**
     * Construct a new {@link Selector}, based on a collection of content.
     * @param <T> the type of content being filtered on
     * @param content the actual content we can filter
     * @return a new selector, used to filter content
     */
    public static <T> Selector<T> from(Collection<T> content) {
        return new Selector<T>(content);
    }

    /**
     * Retrieve all content, performing no restrictions.
     * @return each content element, in list format
     */
    public List<T> list() {
        return new ArrayList<T>(content);
    }

    /**
     * Retrieve all content, that satisfies our matcher criteria.
     * @param matcher provides the matching criteria
     * @return each satisfying content element, in list format
     */
    public List<T> where(Matcher<? super T> matcher) {
        List<T> matches = new ArrayList<T>();
        for (T candidate : content) {
            if (matcher.matches(candidate)) {
                matches.add(candidate);
            }
        }
        return matches;
    }

}
